package com.torfox.modules.livelog;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import lombok.extern.slf4j.Slf4j;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.map.ObjectMapper;
import org.eclipse.jetty.websocket.WebSocket;
import org.hamcrest.Matcher;
import org.springframework.context.ApplicationContext;

import com.torfox.entities.LogRecord;
import com.torfox.services.ILogListener;

@Slf4j
public class LiveLogConnection implements WebSocket, ILogListener
{
	private final ApplicationContext applicationContext;

	private Connection connection;

	private final Matcher<LogRecord> matcher;

	private ObjectMapper mapper;

	public LiveLogConnection(final HttpServletRequest request, final ApplicationContext applicationContext)
    {
		this.applicationContext = applicationContext;
		matcher = MatcherUtils.fromRequest(request);
    }

	@Override
    public void onOpen(final Connection connection)
    {
		this.connection = connection;
		final JsonFactory jf = new JsonFactory();
		mapper = new ObjectMapper(jf);
		applicationContext.publishEvent(new LiveLogConnectEvent(this));
    }

	@Override
    public void onClose(final int closeCode, final String message)
    {
		applicationContext.publishEvent(new LiveLogDisconnectEvent(this));
    }

	@Override
    public void onLog( final LogRecord record)
	{
		if( connection.isOpen() && matcher.matches(record))
		{
			try
            {
	            connection.sendMessage(serializeRecord( record));
            }
            catch (final IOException e)
            {
            	log.error( "Error sending message", e);
            }
            catch (final SerializationException e)
            {
            	log.error( "Serialziation of LogRecord error", e);
            }
		}
	}

	/**
	 * Serializes given record to JSON string
	 * @param record Record to serialize
	 * @throws SerializationException
	 */
	private String serializeRecord(final LogRecord record) throws SerializationException
    {
		try
	    {
			return mapper.writeValueAsString(record);
	    }
		catch( final Exception e)
		{
			throw new SerializationException("Serialization of LogRecord failed", e);
		}
    }

}
